#-*- coding:UTF-8 -*-


import traceback


from .models import PermissionMapping
from .db import *
from ..logger import logger


def save_object(obj):
    with session_context() as session:
        try:
            session.add(obj)
            session.commit()
            return True
        except Exception as ex:
            logger.debug('Exception(%s) in save_object(%s)'%(ex, obj))
            traceback.print_exc()
            return False


def delete_object(obj):
    with session_context() as session:
        try:
            session.delete(obj)
            session.commit()
            return True
        except Exception as ex:
            logger.debug('Exception(%s) in save_object(%s)'%(ex, obj))
            traceback.print_exc()
            return False


'''
def delete_objects(object_class, **kwargs):
    with session_context() as session:
        try:
            query_obj = session.query(object_class)
        except Exception as ex:
            logger.debug('Exception(%s) in delete_objects(%s, **kwargs)'%(ex, object_class))
            traceback.print_exc()
            return 0
'''


def get_object_by_id(object_class, object_id, id_column_name='id' ,attr_list=[], **kwargs):
    e = None
    with session_context() as session:
        try:
            query_obj = session.query(object_class)
            query_obj = query_obj.filter(getattr(object_class, id_column_name)==object_id)
            for key,value in kwargs.items():
                query_obj = query_obj.filter(getattr(object_class, key)==value)
            obj = query_obj.one()
            for attr in attr_list:
                attr_array = attr.split('.')
                _get_deep_attr(obj, attr_array)
            return obj
        except Exception as ex:
            logger.debug('Exception(%s) in get_object_by_id(...)'%ex)
            e = ex
            traceback.print_exc()
    if e:
        return


'''
def get_object_by_ids(object_class, object_id_list, id_column_name_list, attr_list=[], **kwargs):
    e = None
    with session_context() as session:
        try:
            pass
        except Exception as ex:
            logger.debug('Exception(%s) in get_object_by_ids(...)'%ex)
            e = ex
            traceback.print_exc()
    if e:
        return
'''


def count_object(object_class, **kwargs):
    e = None
    with session_context() as session:
        try:
            query_obj = session.query(object_class)
            for key, value in kwargs.items():
                query_obj = query_obj.filter(getattr(object_class,key)==value)
            return query_obj.count()
        except Exception as ex:
            logger.debug('Exception(%s) during count_object'%ex)
            traceback.print_exc()
            e = ex
    if e:
        raise e


def _get_deep_attr(obj, attr_array):
    '''
    get attr of a object(obj)
    obj: object
    attr_array: array of attributes for deep association

    for example: _get_deep_attr(user,['usergroups', 
        'group','groupsysids','sysid','hosts'])
    '''
    next_obj = obj
    if len(attr_array) > 0 :
        if isinstance(next_obj, list) or isinstance(next_obj, tuple):
            for item_obj in next_obj:
                if hasattr(item_obj,attr_array[0]):
                    next_obj = getattr(item_obj,attr_array[0])
                    _get_deep_attr(next_obj,attr_array[1:])
        else:
            if hasattr(next_obj, attr_array[0]):
                next_obj = getattr(next_obj, attr_array[0])
                _get_deep_attr(next_obj,attr_array[1:])


def get_objects(object_class, attr_list=[], **kwargs):
    '''
    get all objects of the same class
    object_class: class of the object you want
    attr_list: list of attributes of the object, also list of str which could has '.' to represent deep association.
    for example: 
        get_objects(User, attr_list=['usergroups.group.groupsysids.sysid.hosts'], name='zhaoxp2')
    '''
    e = None
    with session_context() as session:
        try:
            query_obj = session.query(object_class)
            for key,value in kwargs.items():
                query_obj = query_obj.filter(getattr(object_class,key)==value)
            obj_list = query_obj.all()
            if attr_list:
                for obj in obj_list:
                    for attr in attr_list:
                        attr_array = attr.split('.')
                        _get_deep_attr(obj,attr_array)
            return obj_list
        except Exception as ex:
            logger.debug('Exception(%s) in get_objects(object_class, attr_list=[], **kwargs)'%ex)
            e = ex
            traceback.print_exc()
    if e:
        raise e


def get_resources(actor_class, actor_id, res_class, attr_list=[]):
    '''
    get resources(System or Host) according to actor id and type
    actor_id: ID of user or group
    actor_class: class of actor, User or Group
    res_class: class of the resource, System or Host ...
    attr_list: list of attribute of resource for querying resource
    '''
    actor_type = actor_class.__name__
    res_type   = res_class.__name__
    #actor_type = '%s.%s'%(actor_class.__module__, actor_class.__name__)
    #res_type = '%s.%s'%(res_class.__module__, res_class.__name__)
    with session_context() as session:
        obj_list = session.query(PermissionMapping).\
            filter(PermissionMapping.actor_type==actor_type).\
            filter(PermissionMapping.actor_id==actor_id).\
            filter(PermissionMapping.res_type==res_type).all()
        the_obj_list = []
        for obj in obj_list:
            #class_str_array = obj.res_type.split('.')
            #the_module = importlib.import_module('.'.join(class_str_array[:-1]))
            #the_class = getattr(the_module, class_str_array[-1])
            the_objs = session.query(res_class).filter(res_class.id==obj.res_id).all()
            if the_objs:
                the_obj_list.append(the_objs[0])
                if attr_list:
                    for attr in attr_list:
                        attr_array = attr.split('.')
                        _get_deep_attr(the_objs[0],attr_array)
        return the_obj_list


def get_actors(res_class, res_id, actor_class, attr_list=[]):
    '''
    get actor(Group or User) of resource(System or Host) from PermissionMapping.
    res_class: class of resource(System or Host)
    res_obj: id of resource
    actor_class: class of actor(Group or User)
    return list of actor
    '''
    actor_type = actor_class.__name__
    res_type   = res_class.__name__
    #actor_type = '%s.%s'%(actor_class.__module__, actor_class.__name__)
    #res_type   = '%s.%s'%(res_class.__module__, res_class.__name__)
    with session_context() as session:
        perm_list = session.query(PermissionMapping).\
            filter(PermissionMapping.res_type==res_type).\
            filter(PermissionMapping.res_id==res_id).\
            filter(PermissionMapping.actor_type==actor_type).all()
        the_obj_list = []
        for perm in perm_list:
            #class_str_array = perm.actor_type.split('.')
            #the_module = importlib.import_module('.'.join(class_str_array[:-1]))
            #the_class = getattr(the_module,class_str_array[-1])
            the_objs = session.query(actor_class).filter(actor_class.id==perm.actor_id).all()
            if the_objs:
                the_obj_list.append(the_objs[0])
                if attr_list:
                    for attr in attr_list:
                        attr_array = attr.split('.')
                        _get_deep_attr(the_objs[0],attr_array)
        return the_obj_list
